/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package br.com.fiap.si.graphos;

import edu.uci.ics.jung.algorithms.layout.AbstractLayout;
import edu.uci.ics.jung.algorithms.layout.StaticLayout;
import edu.uci.ics.jung.graph.DirectedSparseMultigraph;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;

import javax.swing.JApplet;
import javax.swing.JFrame;
import javax.swing.JPanel;

import edu.uci.ics.jung.graph.Graph;
import edu.uci.ics.jung.visualization.GraphZoomScrollPane;
import edu.uci.ics.jung.visualization.VisualizationViewer;
import edu.uci.ics.jung.visualization.control.CrossoverScalingControl;
import edu.uci.ics.jung.visualization.control.EditingModalGraphMouse;
import edu.uci.ics.jung.visualization.control.ModalGraphMouse;
import edu.uci.ics.jung.visualization.control.ScalingControl;
import edu.uci.ics.jung.visualization.decorators.EdgeShape;
import edu.uci.ics.jung.visualization.decorators.ToStringLabeller;
import edu.uci.ics.jung.visualization.picking.PickedState;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.io.IOException;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JOptionPane;
import org.apache.commons.collections15.Factory;
import edu.uci.ics.jung.io.GraphMLWriter;
import java.io.FileWriter;
import javax.swing.JFileChooser;
import org.apache.commons.collections15.Transformer;

/**
 * Demonsrates TreeLayout and RadialTreeLayout.
 *
 * @author Tom Nelson
 *
 */
@SuppressWarnings("serial")
public class jungExample extends JApplet {

    Graph<String, String> graph;
    VisualizationViewer<String, String> vv;
    AbstractLayout<String, String> layout;
    public String verticeSelecionado = "";
    public String arestaSelecionada = "";
    public String verticeInicial = "";
    public String verticeFinal = "";
    public ArrayList<String> verticesVisitados = new ArrayList<String>();
    public ArrayList<String> arestasVisitadas = new ArrayList<String>();
    private final static int VALOR_COMBO_ANNOTATING = 3;

    public jungExample() {

        graph = new DirectedSparseMultigraph<String, String>();
        this.layout = new StaticLayout<String, String>(graph, new Dimension(600, 600));
        vv = new VisualizationViewer<String, String>(layout, new Dimension(600, 600));
        vv.setBackground(Color.white);
        vv.getRenderContext().setEdgeShapeTransformer(new EdgeShape.QuadCurve());
        vv.getRenderContext().setVertexLabelTransformer(new ToStringLabeller());
        vv.getRenderContext().setEdgeLabelTransformer(new ToStringLabeller());

        Container content = getContentPane();
        final GraphZoomScrollPane panel = new GraphZoomScrollPane(vv);
        content.add(panel);
        Factory<String> vertexFactory = new jungExample.VertexFactory();
        Factory<String> edgeFactory = new jungExample.EdgeFactory();

        final EditingModalGraphMouse<String, String> graphMouse =
                new EditingModalGraphMouse<String, String>(vv.getRenderContext(), vertexFactory, edgeFactory);

        // the EditingGraphMouse will pass mouse event coordinates to the
        // vertexLocations function to set the locations of the vertices as
        // they are created
        //        graphMouse.setVertexLocations(vertexLocations);
        vv.setGraphMouse(graphMouse);
        vv.addKeyListener(graphMouse.getModeKeyListener());

        graphMouse.setMode(ModalGraphMouse.Mode.EDITING);

        final ScalingControl scaler = new CrossoverScalingControl();

        JButton btnRemover = new JButton("Remover");
        //btnRemover.setEnabled(false);
        btnRemover.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                scaler.scale(vv, 1 / 1.1f, vv.getCenter());

                if (!verticeSelecionado.isEmpty()) {
                    graph.removeVertex(verticeSelecionado);
                } else if (!arestaSelecionada.isEmpty()) {
                    graph.removeEdge(arestaSelecionada);
                }
                layout.setGraph(graph);
                vv.repaint();
            }
        });

        JButton btnExportar = new JButton("Exportar");
        btnExportar.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                scaler.scale(vv, 1 / 1.1f, vv.getCenter());
                if (verticeInicial.isEmpty() || !graph.containsVertex(verticeInicial)) {
                    JOptionPane.showMessageDialog(null, "Voce deve selecionar o vértice inicial para exportar um arquivo", "Aviso", JOptionPane.INFORMATION_MESSAGE);
                } else {
                    CriarXML();
                }
            }
        });

        JButton btnDefinirInicio = new JButton("Definir Inicio");
        btnDefinirInicio.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                scaler.scale(vv, 1 / 1.1f, vv.getCenter());
                if (verticeSelecionado.equals("")) {
                    JOptionPane.showMessageDialog(null, "Você deve selecionar um vértice para definir o início do grafo", "Aviso", JOptionPane.INFORMATION_MESSAGE);
                } else {
                    verticeInicial = verticeSelecionado;
                    JOptionPane.showMessageDialog(null, "O Vertice inicial foi definido!", "Aviso", JOptionPane.INFORMATION_MESSAGE);
                }
            }
        });

        // Attach the listener for listening to when vertices are selected (or deselected).
        // You can also listen for changes to the selection of edges, by using vv.getPickedEdgeState() in
        // place of vv.getPickedVertexState().
        // vertice(no)
        final PickedState<String> pickedStateVertex = vv.getPickedVertexState();

        pickedStateVertex.addItemListener(
                new ItemListener() {
            @Override
            public void itemStateChanged(ItemEvent e) {
                Object subject = e.getItem();
                if (subject instanceof String) {
                    String vertex = (String) subject;
                    if (pickedStateVertex.isPicked(vertex)) {
                        verticeSelecionado = vertex;
                    } else {
                        verticeSelecionado = "";
                    }
                }
            }
        });

        //aresta
        final PickedState<String> pickedStateEdge = vv.getPickedEdgeState();

        pickedStateEdge.addItemListener(
                new ItemListener() {
            @Override
            public void itemStateChanged(ItemEvent e) {
                Object subject = e.getItem();
                if (subject instanceof String) {
                    String edge = (String) subject;
                    if (pickedStateEdge.isPicked(edge)) {
                        arestaSelecionada = edge;
                    } else {
                        arestaSelecionada = "";
                    }
                }
            }
        });

        JComboBox modeBox = graphMouse.getModeComboBox();
        modeBox.removeItemAt(VALOR_COMBO_ANNOTATING);
        modeBox.addItemListener(graphMouse.getModeListener());
        JPanel controls = new JPanel();
        controls.add(btnDefinirInicio);
        controls.add(modeBox);
        controls.add(btnExportar);
        content.add(controls, BorderLayout.SOUTH);
    }

    /**
     *
     */
    public void ChamarGrapho() {
        JFrame frame = new JFrame();

        Container content = frame.getContentPane();

        content.add(new jungExample());
        frame.pack();
        frame.setVisible(true);
    }

    public void CriarXML() {
        try {
            JFileChooser chooser = new JFileChooser();
            String caminhoArquivo = "";
            int retorno = chooser.showSaveDialog(null);
            if (retorno == JFileChooser.APPROVE_OPTION) {
                caminhoArquivo = chooser.getSelectedFile().getAbsolutePath();
            }
            if (!caminhoArquivo.equals("")) {
                GraphMLWriter<String, String> graphWriter = new GraphMLWriter();

                //Anota os valores das posições do grafo(Coordenadas X e Y).
                graphWriter.addVertexData("descricao", null, "nada",
                        new Transformer<String, String>() {
                    @Override
                    public String transform(String v) {
                        if (v.equals(verticeInicial)) {
                            return "Inicio";
                        } else if (graph.getSuccessorCount(v) == 0) {
                            return "Fim";
                        } else {
                            return "nada";
                        }
                    }
                });

                //Anota os valores das arestas do grafo(já que por padrão, ele não grava).
                graphWriter.addEdgeData("respostas", null, "", new Transformer<String, String>() {
                    @Override
                    public String transform(String v) {
                        return v;
                    }
                });
                FileWriter out = new FileWriter(caminhoArquivo);
                graphWriter.save(graph, out);
                JOptionPane.showMessageDialog(null, "O grafo foi exportado com sucesso!");
            }
        } catch (IOException ex) {
            Logger.getLogger(jungExample.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    class VertexFactory implements Factory<String> {

        @Override
        public String create() {
            String valorVertice = JOptionPane.showInputDialog("Digite o valor do vértice");

            if (!valorVertice.trim().isEmpty()) {
                return valorVertice;
            } else {
                return null;
            }
        }
    }

    class EdgeFactory implements Factory<String> {

        @Override
        public String create() {

            String valorAresta = JOptionPane.showInputDialog("Digite os valores das arestas(separar as respostas diferentes com ;)");

            if (!valorAresta.trim().isEmpty()) {
                return valorAresta;
            } else {
                return null;
            }
        }
    }
}
